Delete a node from a singly-linked list, given only a variable pointing to that node.
The input could, for example, be the variable b below:
class LinkedListNode(object):
def __init__(self, value):
self.value = value
self.next = None
a = LinkedListNode('A')
b = LinkedListNode('B')
c = LinkedListNode('C')
a.next = b
b.next = c
delete_node(b)
We take value and next from the input node's next node and copy them into the input node. Now the input node's previous node effectively skips the input node's old value!
So for example, if this was our linked list before we called our function:
This would be our list after we called our function:
In some languages, like C, we'd have to manually delete the node we copied from, since we won't be using that node anymore. Here, we'll let Python's garbage collector take care of it.
def delete_node(node_to_delete):
# Get the input node's next node, the one we want to skip to
next_node = node_to_delete.next
if next_node:
# Replace the input node's value and pointer with the next
# node's value and pointer. The previous node now effectively
# skips over the input node
node_to_delete.value = next_node.value
node_to_delete.next = next_node.next
else:
# Eep, we're trying to delete the last node!
raise Exception("Can't delete the last node with this technique!")
But be careful—there are some potential problems with this implementation:
First, it doesn't work for deleting the last node in the list. We could change the node we're deleting to have a value of None, but the second-to-last node's next pointer would still point to a node, even though it should be None. This could work—we could treat this last, "deleted" node with value None as a "dead node" or a "sentinel node," and adjust any node traversing code to stop traversing when it hits such a node. The trade-off there is we couldn't have non-dead nodes with values set to None. Instead we chose to throw an exception in this case.
Second, this technique can cause some unexpected side-effects. For example, let's say we call:
a = LinkedListNode(3)
b = LinkedListNode(8)
c = LinkedListNode(2)
a.next = b
b.next = c
delete_node(b)
There are two potential side-effects:
time and space.
My favorite part of this problem is how imperfect the solution is. Because it modifies the list "in place" it can cause other parts of the surrounding system to break. This is called a "side effect."
In-place operations like this can save time and/or space, but they're risky. If you ever make in-place modifications in an interview, make sure you tell your interviewer that in a real system you'd carefully check for side effects in the rest of the code base.
Do you have an answer?
Wanna review this one again later? Or do you feel like you got it all?
Mark as done Pin for review laterReset editor
Powered by qualified.io